import json
import uuid
import copy
from typing import Union
from apis import api_routes
from flask import abort, g, request, jsonify
from models.users.roles import Roles
from models.users.users import Users
from security.decoration import certification
from sqlalchemy import text
from security.security import encode_jwt
from public.local import datetime_type
from security.security import decode_jwt
from typing import List
from models.facility.facility import Facility
from sqlalchemy import and_
from models.product.craft import Craft
from models.product.routes import Routes
from models.product.aircraft import Aircraft
from public.config import config
from sqlalchemy.sql import func


allow: list = ["Bool", "Short", "Int", "Float", "String"]
translate: list = ["布尔类型", "整数16位", "整数32位", "浮点型", "字符串类型"]


@api_routes.route("/craft/station", methods=["GET"])
@certification(auth=True, role=None)
def func_craft_station_get_api():
    """
    查询全部绑定PLC设备，没有做分页, 完成API开发
    http://127.0.0.1:8080/api/craft/station
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    :return:
        {'status': 200, 'data': resp}
    ---
    tags:
      - 工艺参数管理模块
    """
    resp: list = []
    data: List[Facility] = g.session.query(Facility).order_by(Facility.id).all()
    for index, itr in enumerate(data):
        if itr.uuid4 is not None:
            resp.append({
                "facility_id": itr.id,
                "name": itr.name,
                "station": itr.station,
                "serials": itr.serials
            })
    return jsonify({'status': 200, 'data': resp})


@api_routes.route("/craft/config", methods=["GET"])
@certification(auth=True, role=None)
def func_craft_config_get_api():
    """
    查询MES系统模式（开发者模式，不是开发者模式）, 完成API开发
    http://127.0.0.1:8080/api/craft/config
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    :return:
        {'status': 200, 'data': resp}
    ---
    tags:
      - 工艺参数管理模块
    """
    return jsonify({'status': 200, 'data': config.DEVELOP})


@api_routes.route("/craft/type", methods=["GET"])
@certification(auth=True, role=None)
def func_craft_type_get_api():
    """
    查询PLC支持数据类型， /api/craft POST  types 要用到, 完成API开发
    http://127.0.0.1:8080/api/craft/type
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    :return:
        {'status': 200, 'data': resp}
    ---
    tags:
      - 工艺参数管理模块
    """

    return jsonify({'status': 200, 'data': allow, "translate": dict(zip(allow, translate))})


@api_routes.route("/craft", methods=["GET"])
@certification(auth=True, role=None)
def func_craft_get_api():
    """
    根据设备查询设备实际值, 以设备为单位， 不做分页, 不需要开发者模式，完成API开发
    前端需要做实时刷新数据， ”real_value“ 会变
    http://127.0.0.1:8080/api/craft
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    {
    "facility_id"   int       设备ID(可选择)，没有全部查询
    }
    :return:
        {'status': 400, 'data': data}
    ---
    tags:
      - 工艺参数管理模块
    """
    ft_id = request.args.get("facility_id", default=None, type=int)
    resp: list = []

    docs: dict = {
        "craft_id": "d对应数据库ID",
        "facility_id": "设备ID",
        "facility_name": "设备名字",
        "facility_serials": "设备序列",
        "address": "PLC地址",
        "types": "PLC数据类型",
        "describe": "PLC变量描述",
        "real_value": "PLC实际值",
        "write": "设备参数写入值",
        "compare": "是否启用上下限数据限制",
        "upper": "最大值",
        "floor": "最小值"
    }

    return jsonify({'status': 200, 'data': resp, "docs": docs, "translate": dict(zip(allow, translate))})


@api_routes.route("/craft/parm", methods=["PUT"])
@certification(auth=True, role=None)
def func_craft_parm_put_api():
    """
    修改上下限值，是否启用是否启用上下限数据限制设备，不需要开发者模式
    http://127.0.0.1:8080/api/craft/parm
    Content-Type=application/json
    methods=["PUT"]
    {
    "craft_id"       int        ****    数据库ID(数据库的)
    "write"          string             设备参数值(数据类型要判断, 如INT类型不能写入String类型)
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
        {'status': 4000, 'msg': "没有找到要跟新数据源"}
        {'status': 4001, 'msg': "非阿拉伯数据类型无法更新"}
        {'status': 4002, 'msg': "写入参数数据类型错误"}
        {'status': 200, 'msg': "修改参数成功", }
    ---
    tags:
      - 工艺参数管理模块
    """
    data: dict = request.get_json()
    craft_id: int = data.get("craft_id")
    write = data.get("write")

    if craft_id is None:
        abort(400)

    craft: Union[Craft, None] = g.session.query(Craft).filter(Craft.id == craft_id).first()
    if craft is None:
        return jsonify({'status': 4000, 'msg': "没有找到要跟新数据源"})

    if write is not None and len(write) > 0:
        values: Union[bool, None] = False
        # noinspection PyBroadException
        try:
            if craft.types in ["Short", "Int"]:
                if len(str(write)) != 0:
                    int(str(write))
                    values = True
                else:
                    values = None
            elif craft.types in ["Float"]:
                if len(str(write)) != 0:
                    float(str(write))
                    values = True
                else:
                    values = None
            elif craft.types in ["Bool"]:
                if write not in ['', "True", "False"]:
                    values = False
                else:
                    values = True
            elif craft.types in ["String"]:
                if len(str(write)) != 0:
                    if len(str(write)) == 0:
                        values = False
                    else:
                        values = True
                else:
                    values = None
        except Exception as e:
            values = False

        if values is False:
            return jsonify({'status': 4001, 'msg': "写入PLC地址数据类型错误"})
        craft.write = write
    else:
        craft.write = None

    g.session.commit()
    return jsonify({'status': 200, 'msg': "修改参数成功"})


@api_routes.route("/craft/write", methods=["POST"])
@certification(auth=True, role=None)
def func_craft_write_post_api():
    """
    设备参数写入PLC，不需要开发者模式
    http://127.0.0.1:8080/api/craft/write
    Content-Type=application/json
    methods=["POST"]
    {
    "craft_id"       int        ****    数据库ID(数据库的)
    }
    :return:
        {'status': 4000, 'msg': "没有找到要跟新数据源"}
        {'status': 4001, 'msg': "没有找到对应设备或者该设备不支持PLC"}
        {'status': 4003, 'msg': "设备参数写入值为空，不支持写入"}
        {'status': 200, 'msg': "参数写入PLC成功", }
    ---
    tags:
      - 工艺参数管理模块
    """
    data: dict = request.get_json()
    craft_id: int = data.get("craft_id")

    if not craft_id:
        abort(400)

    craft: Union[Craft, None] = g.session.query(Craft).filter(Craft.id == craft_id).first()
    if craft is None:
        return jsonify({'status': 4000, 'msg': "没有找到要跟新数据源"})
    fty: Facility = g.session.query(Facility).filter(Facility.id == craft.facility_id).first()
    if fty is None or fty.uuid4 is None:
        return jsonify({'status': 4001, 'msg': "没有找到对应设备或者该设备不支持PLC"})

    types: str = craft.types
    key: str = "queues{}".format(str(fty.uuid4).replace("-", ""))

    # ["Bool", "Short", "Int", "Float", "String"]:
    if craft.write is not None and craft.types in ["Bool", "Short", "Int", "Float"] and len(craft.write) != 0:
        g.cache.rpush(key, json.dumps({"address": craft.address, "type": types, "value": craft.write}))
        g.cache.expire(key, 16)
    elif craft.write is not None and craft.types == "String":
        g.cache.rpush(key, json.dumps({"address": craft.address, "type": types, "value": craft.write}))
        g.cache.expire(key, 16)

    return jsonify({'status': 200, 'msg': "参数写入PLC成功"})


@api_routes.route("/craft", methods=["DELETE"])
@certification(auth=True, role=None)
def func_craft_delete_api():
    """
    删除设备IO点，需要开发者模式下才能操作，完成API开发
    http://127.0.0.1:8080/api/craft
    Content-Type=application/json
    methods=["DELETE"]
    {
    "facility_id"      string     ****    工位名称
    "serial"    string     ****    工位编号
    "enable"    int(1或者0) ****    是否在看板展示
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
        {'status': 403, 'msg': "token无效或者未登录或没有权限"}
        {'status': 4000, 'msg': "已经存在此用户"}
        {'status': 200, 'msg': "添加账户成功", }
    ---
    tags:
      - 工艺参数管理模块
    """
    data: dict = request.get_json()
    craft_id: str = data.get("craft_id")

    if config.DEVELOP is not True:
        return jsonify({'status': 3999, 'msg': "不是开发者模式禁止删除PLC变量"})

    craft: Union[Craft, None] = g.session.query(Craft).filter(Craft.id == craft_id).first()
    if craft is not None:
        return jsonify({'status': 4000, 'msg': "没有找到数据无法删除"})

    g.session.query(Craft).filter(Craft.id == craft_id).delete()
    g.session.commit()
    return jsonify({'status': 200, 'msg': "删除成功"})
